﻿using Common.Communication;
using Common.Device;
using Common.Device.DeviceDb;
using Common.Device.Enums;
using Common.Device.Interfaces;
using Common.Device.Models;
using Common.Tool.DataTools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AnGuiYi.JueYuanNaiYa
{
    public class TH9201BSerialPort:SerialPortBase, IJueYuanNaiYa
    {
        public string Name { get; set; }
        public TH9201BSerialPort(UseDevice device) : base(device.port, Convert.ToInt32(device.parameter), timeout: 1500)
        {
            Name = device.name;
        }


        public Result<List<JueYuanNaiYaResult>> SetTest(Common.Device.Models.JueYuanNaiYa parameter)
        {
            lock (this)
            {
                var result = new Result<List<JueYuanNaiYaResult>>(new List<JueYuanNaiYaResult>());
                var write = new Result();
                var read = new Result<string>();
                string type = "";
                int fun = 0;
                double min = 0.0, max = 0.0;
                string unit = "";
                switch (parameter.mode)
                {
                    case AnGuiYiEnum.TestMode.绝缘电阻:
                        type = "IR";
                        unit = "MΩ";
                        fun = 3;
                        min = (parameter.下限值 ?? 0) * 1;
                        max = (parameter.上限值 ?? 0) * 1;
                        break;
                    case AnGuiYiEnum.TestMode.直流耐压:
                        type = "DC";
                        unit = "uA";
                        fun = 2;
                        min = (parameter.下限值 ?? 0) / 1000;
                        max = (parameter.上限值 ?? 0) / 1000;
                        break;
                    case AnGuiYiEnum.TestMode.交流耐压:
                        type = "AC";
                        unit = "uA";
                        min = (parameter.下限值 ?? 0) / 1000;
                        max = (parameter.上限值 ?? 0) / 1000;
                        fun = 1;
                        break;
                    default:
                        break;
                }
                AppendInfo(Name, $"新增测试方案");
                read = WriteThenRead(CmdNew(1),wait:100);
                if (!read.IsSucceed || !read.Value.Contains(CmdSetOk))
                {
                    result.IsSucceed = false;
                    result.Err = "新增测试方案失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, "新增测试方案成功");
                Thread.Sleep(150);
                AppendInfo(Name, $"设置{type}");
                write = Write(CmdSetFun(fun));
                if (!read.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = $"设置{type}失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置{type}成功");
                Thread.Sleep(150);
                AppendInfo(Name, $"设置蜂鸣器OFF");
                write = Write(CmdSetBeep("OFF"));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置蜂鸣器失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(150);
                //发送指令并返回
                read = WriteThenRead(CmdGetBeep, wait: 100);
                if (!read.IsSucceed || !read.Value.Contains("OFF"))
                {
                    result.IsSucceed = false;
                    result.Err = "设置蜂鸣器失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, "设置蜂鸣器成功");
                AppendInfo(Name, $"设置测试参数");
                AppendInfo(Name, $"步骤检查{1}");
                read = WriteThenRead(CmdGetStep, wait: 100);
                if (!read.IsSucceed || !read.Value.Contains(fun+","))
                {
                    result.IsSucceed = false;
                    result.Err = "步骤检查失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }

                if (parameter.mode == AnGuiYiEnum.TestMode.交流耐压)
                {
                    AppendInfo(Name, $"设置频率{parameter.电压频率}Hz");
                    write = Write(CmdFreq(parameter.电压频率, 1));
                    if (!write.IsSucceed)
                    {
                        result.IsSucceed = false;
                        result.Err = "设置频率失败";
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                    }
                    Thread.Sleep(150);
                    read = WriteThenRead(CmdGetFreq(1), wait: 100);
                    if (!read.IsSucceed || !int.TryParse(read.Value, out int va) || va != parameter.电压频率)
                    {
                        result.IsSucceed = false;
                        result.Err = "设置频率失败";
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                    }
                }
                if (parameter.mode == AnGuiYiEnum.TestMode.交流耐压 || parameter.mode == AnGuiYiEnum.TestMode.直流耐压)
                {
                    AppendInfo(Name, $"设置电弧{parameter.电弧值}mA");
                    write = Write(CmdArc(type, parameter.电弧值/1000, 1));
                    if (!write.IsSucceed)
                    {
                        result.IsSucceed = false;
                        result.Err = "设置电弧失败";
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                    }
                    Thread.Sleep(150);
                    read = WriteThenRead(CmdGetArc(type, 1), wait: 100);
                    if (!read.IsSucceed || !double.TryParse(read.Value, out double arc) || arc != (parameter.电弧值 / 1000) )
                    {
                        result.IsSucceed = false;
                        result.Err = "设置电弧失败";
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                    }
                }
                AppendInfo(Name, $"设置电压{parameter.电压值}kV");
                write = Write(CmdSetVol(parameter.电压值*1000, 1, type));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置电压失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(150);
                read = WriteThenRead(CmdGetVol(1, type), wait: 100);
                if (!read.IsSucceed || !double.TryParse(read.Value, out double v) || v != parameter.电压值*1000)
                {
                    result.IsSucceed = false;
                    result.Err = "设置电压失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置上升时间{parameter.上升时间}s");
                write = Write(CmdUpTime(parameter.上升时间, 1, type));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置上升时间失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(150);
                read = WriteThenRead(CmdGetUpTime(1, type), wait: 100);
                if (!read.IsSucceed || !double.TryParse(read.Value, out double ut) || ut != parameter.上升时间)
                {
                    result.IsSucceed = false;
                    result.Err = "设置上升时间失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置保持时间{parameter.测试时间}s");
                write = Write(CmdKeepTime(parameter.测试时间, 1, type));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置保持时间失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(150);
                read = WriteThenRead(CmdGetKeepTime(1, type), wait: 100);
                if (!read.IsSucceed || !double.TryParse(read.Value, out double kt) || kt != parameter.测试时间)
                {
                    result.IsSucceed = false;
                    result.Err = "设置保持时间失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置下降时间{parameter.下降时间}s");
                write = Write(CmdDownTime(parameter.下降时间, 1, type));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置下降时间失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(150);
                read = WriteThenRead(CmdGetDownTime(1, type), wait: 100);
                if (!read.IsSucceed || !double.TryParse(read.Value, out double dt) || dt != parameter.下降时间)
                {
                    result.IsSucceed = false;
                    result.Err = "设置下降时间失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置上限{max}");
                write = Write(CmdMax(max, 1, type));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置上限失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(150);
                read = WriteThenRead(CmdGetMax(1, type), wait: 100);
                if (!read.IsSucceed || !double.TryParse(read.Value, out double ma) || ma != max)
                {
                    result.IsSucceed = false;
                    result.Err = "设置上限失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                if (type != "AC")
                {
                    AppendInfo(Name, $"设置下限{min}");
                    write = Write(CmdMin(min, 1, type));
                    if (!write.IsSucceed)
                    {
                        result.IsSucceed = false;
                        result.Err = "设置下限失败";
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                    }
                }
                Thread.Sleep(150);
                read = WriteThenRead(CmdGetMin(1, type), wait: 100);
                if (!read.IsSucceed || !double.TryParse(read.Value, out double mi) || mi != min)
                {
                    result.IsSucceed = false;
                    result.Err = "设置下限失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置测试参数成功");
                Thread.Sleep(200);
                    AppendInfo(Name, $"开始测试");
                    write = Write(CmdStart);
                    if (!write.IsSucceed)
                    {
                        result.IsSucceed = false;
                        result.Err = "开始测试失败";
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                    }
                
                DateTime testTime = DateTime.Now.AddSeconds(parameter.上升时间+parameter.测试时间+parameter.下降时间+3);
                while (DateTime.Now < testTime)
                {
                    Thread.Sleep(500);
                    if (DeviceService.IsStop)
                    {
                        Write(CmdStop);
                        result.IsSucceed = false;
                        result.Err = "停止测试";
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                    }
                    //todo 失败停止
                }
                read = WriteThenRead(CmdFetch, wait: 100);
                if (!read.IsSucceed || !read.Value.Contains(","))
                {
                    Write(CmdStop);
                    result.IsSucceed = false;
                    result.Err = "测试失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                //解析测试结果 Judge,Judge1,Judge2,…Judgen,Data1, Data 2,…, Datan 
                var value = read.Value.Substring(2).Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < value.Length / 2; i++)
                {
                    JueYuanNaiYaResult jueYuanNai = new JueYuanNaiYaResult()
                    {
                        type = type,
                        value = parameter.电压值 + "kV," + float.Parse(value[value.Length / 2 + i]) + unit,
                        isPass = value[i] == "1"
                    };
                    result.Value.Add(jueYuanNai);
                    AppendResult(Name, jueYuanNai.type + "," + jueYuanNai.value + "," + jueYuanNai.isPass);
                }
                result.IsSucceed = result.Value.Count(o => o.isPass == false) == 0;
                if (!result.IsSucceed)
                    result.Err = "测试未通过";
                return result.EndTime();
            }
        }

        public Result<bool> StopTest()
        {
            lock (this)
            {
                var result = new Result<bool>();
                var write = new Result();
                AppendInfo(Name, $"停止测试");
                List<string> temps = new List<string>();
                var command = CmdStop;
                write = Write(command);
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "停止测试失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"停止测试成功");
                return result.EndTime();
            }
        }
        public double IrVolMin = 0.05f;
        public double IrVolMax = 1;
        public double TimeMin = 0.1f;
        public double TimeMax = 999.9f;
        public double IrMin = 0.01f;
        public double IrMax = 10000;
        public double DcwVolMin = 0.05f;
        public double DcwVolMax = 6f;
        public double DcwMin = 0.0001f;
        public double DcwMax = 5;
        public double AcwVolMin = 0.05f;
        public double AcwVolMax = 5f;
        public double AcwMin = 0.001f;
        public double AcwMax = 10;
        string CmdId => "*IDN?\n";
        string CmdNew(int step) => $":SOUR:SAFE:NEW {step}\n";
        string CmdSetOk => "1";
        string CmdGetStep => ":SOUR:SAFE:FUNC?\n";
        string CmdSetFun(int fun) => $":SOUR:SAFE:STEP 1:FUNC {fun}\n";
        string CmdSetBeep(string beep) { return ":SYST:BEEP " + beep + "\n"; }
        string CmdGetBeep => ":SYST:BEEP?\n";
        string CmdSetVol(double vol, int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":LEV " + vol + "\n"; }
        string CmdGetVol(int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":LEV?\n"; }
        string CmdUpTime(double upTime, int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":TIME:RAMP " + upTime + "\n"; }
        string CmdGetUpTime(int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":TIME:RAMP?\n"; }
        string CmdKeepTime(double keepTime, int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":TIME:TEST " + keepTime + "\n"; }
        string CmdGetKeepTime(int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":TIME:TEST?\n"; }
        string CmdDownTime(double downTime, int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":TIME:FALL " + downTime + "\n"; }
        string CmdGetDownTime(int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":TIME:FALL?\n"; }
        string CmdFreq(int freq, int step) { return ":SOUR:SAFE:STEP " + step + ":AC:FREQ " + freq + "\n"; }
        string CmdGetFreq(int step) { return ":SOUR:SAFE:STEP " + step + ":AC:FREQ?\n"; }
        string CmdArc(string type, double arc, int step) { return ":SOUR:SAFE:STEP " + step + $":{type}:LIM:ARC " + arc + "\n"; }
        string CmdGetArc(string type, int step) { return ":SOUR:SAFE:STEP " + step + $":{type}:LIM:ARC?\n"; }
        string CmdMax(double max, int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":LIM:HIGH " + max + "\n"; }
        string CmdGetMax(int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":LIM:HIGH?\n"; }
        string CmdMin(double min, int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":LIM:LOW " + min + "\n"; }
        string CmdGetMin(int step, string type) { return ":SOUR:SAFE:STEP " + step + ":" + type + ":LIM:LOW?\n"; }
        string CmdStart => ":SOUR:SAFE:START\n";
        string CmdStop => ":SOUR:SAFE:STOP\n";
        string CmdFetch => ":TEST:FETCH?\n";
    }
}
